package com.jingfu.Service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.jingfu.Service.RoleService;
import com.jingfu.common.BadRequestException;
import com.jingfu.common.ErrorCode;
import com.jingfu.dto.*;
import com.jingfu.mapper.SysPowerMapper;
import com.jingfu.mapper.SysRoleMapper;
import com.jingfu.mapper.SysRolePowerMapper;
import com.jingfu.pojo.SysPower;
import com.jingfu.pojo.SysRole;
import com.jingfu.pojo.SysRolePower;
import com.jingfu.util.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jingfuu@163.com
 * @version v1.0
 * @date 2022/2/1 下午7:35
 **/
@Service
@Slf4j
public class RoleServiceImpl implements RoleService {
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysPowerMapper sysPowerMapper;
    @Autowired
    private SysRolePowerMapper sysRolePowerMapper;

    @Override
    public List<SysRoleDTO> getRoleList(SysRoleDTO sysRoleDTO) {
        return sysRoleMapper.getRoleList(sysRoleDTO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void roleEnable(String roleId, String enable) {
        SysRole sysRole = sysRoleMapper.selectByPrimaryKey(roleId);
        if (Objects.isNull(sysRole)) {
            throw new BadRequestException(ErrorCode.PARAM_IS_ERROR);
        }
        sysRole.setEnable(enable);
        int i = sysRoleMapper.updateByPrimaryKey(sysRole);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createOrUpdateRole(SysRoleDTO sysRoleDTO) {
        if (Objects.nonNull(sysRoleDTO.getRoleId())) {
            //更新
            SysRole sysRole = sysRoleMapper.selectByPrimaryKey(sysRoleDTO.getRoleId());
            if (Objects.isNull(sysRole)) {
                throw new BadRequestException(ErrorCode.PARAM_IS_ERROR);
            }
            if (!StrUtil.equals(sysRole.getRoleCode(), sysRoleDTO.getRoleCode())) {
                checkRoleCode(sysRoleDTO.getRoleCode());
            }
            sysRole.setRoleCode(sysRoleDTO.getRoleCode());
            sysRole.setDetails(sysRoleDTO.getDetails());
            sysRole.setRoleName(sysRoleDTO.getRoleName());
            sysRole.setUpdateTime(Date.from(Instant.now()));
            UserUtil.getCurrentUser().ifPresent(userDetail -> sysRole.setUpdateBy(userDetail.getUsername()));
            sysRoleMapper.updateByPrimaryKeySelective(sysRole);
            return;
        }
        //新增
        //校验权限标识不能重复
        checkRoleCode(sysRoleDTO.getRoleCode());
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(sysRoleDTO,sysRole);
        sysRole.setRoleId(IdUtil.objectId());
        sysRole.setCreateTime(Date.from(Instant.now()));
        UserUtil.getCurrentUser().ifPresent(userDetail -> sysRole.setCreateBy(userDetail.getUsername()));
        sysRole.setEnable("1");
        sysRoleMapper.insert(sysRole);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteRole(String roleId) {
        SysRole sysRole = sysRoleMapper.selectByPrimaryKey(roleId);
        if (Objects.isNull(sysRole)) {
            throw new BadRequestException(ErrorCode.PARAM_IS_ERROR);
        }
        sysRole.setStatus("0");
        sysRoleMapper.updateByPrimaryKeySelective(sysRole);
    }

    @Override
    public List<SysPowerDTO> getRolePermList(String roleId) {
        return sysPowerMapper.findAllByRoleId(roleId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createRolePerm(RolePermDTO rolePermDTO) {
        //该角色对应原始菜单权限
        List<SysPowerDTO> rolePermList = getRolePermList(rolePermDTO.getRoleId());
        List<String> originalPermIdList = rolePermList.stream()
                .map(sysPowerDTO -> sysPowerDTO.getPowerId())
                .collect(Collectors.toList());
        //新增的权限
        if (CollUtil.isEmpty(rolePermList)) {
            createRolePerm(rolePermDTO.getRoleId(),rolePermDTO.getPermIds());
            return;
        }
        List<String> createPermIds = rolePermDTO.getPermIds().stream().filter((permId) -> !originalPermIdList.contains(permId)).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(createPermIds)) {
            createRolePerm(rolePermDTO.getRoleId(),createPermIds);
        }
        //删除的权限
        List<String> deletePermIds = originalPermIdList.stream().filter((permId) -> !rolePermDTO.getPermIds().contains(permId)).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(deletePermIds)) {
            sysRolePowerMapper.deleteRolePerm(rolePermDTO.getRoleId(),deletePermIds);
        }
    }

    @Override
    public List<PowerDTO> getPermList(PowerDTO powerDTO) {
        List<PowerDTO> permList = sysPowerMapper.getPermList(powerDTO);
        //排序，用于前端树形结构展示
        LinkedList<PowerDTO> powerDTOS = new LinkedList<>();
        sort(permList,powerDTOS,"0");
        return powerDTOS;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void permEnable(String powerId, String enable) {
        SysPower sysPower = sysPowerMapper.selectByPrimaryKey(powerId);
        if (Objects.isNull(sysPower)) {
            throw new BadRequestException(ErrorCode.PARAM_IS_ERROR);
        }
        sysPower.setEnable(enable);
        int i = sysPowerMapper.updateByPrimaryKey(sysPower);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deletePermission(String powerId) {
        SysPower sysPower = sysPowerMapper.selectByPrimaryKey(powerId);
        if (Objects.isNull(sysPower)) {
            throw new BadRequestException(ErrorCode.PARAM_IS_ERROR);
        }

        sysPower.setStatus("0");
        int i = sysPowerMapper.updateByPrimaryKeySelective(sysPower);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void permissionCreateOrUpdate(PowerDTO powerDTO) {
        if (Objects.nonNull(powerDTO.getPowerId())) {
            //更新
            SysPower sysPower = sysPowerMapper.selectByPrimaryKey(powerDTO.getPowerId());
            if (Objects.isNull(sysPower)) {
                throw new BadRequestException(ErrorCode.PARAM_IS_ERROR);
            }
            sysPower.setPowerName(powerDTO.getPowerName());
            sysPower.setPowerCode(powerDTO.getPowerCode());
            sysPower.setPowerType(powerDTO.getPowerType());
            sysPower.setPowerUrl(powerDTO.getPowerUrl());
            sysPower.setParentId(powerDTO.getParentId());
            sysPower.setIcon(powerDTO.getIcon());
            sysPower.setSort(powerDTO.getSort());
            sysPower.setUpdateTime(Date.from(Instant.now()));
            UserUtil.getCurrentUser().ifPresent(userDetail -> sysPower.setUpdateBy(userDetail.getUsername()));
            sysPowerMapper.updateByPrimaryKeySelective(sysPower);
            return;
        }
        //新增
        SysPower sysPower = new SysPower();
        BeanUtils.copyProperties(powerDTO,sysPower);
        if ("0".equals(powerDTO.getPowerType()) && StrUtil.isBlank(powerDTO.getParentId())){
            sysPower.setParentId("0");
        }
        sysPower.setPowerId(IdUtil.objectId());
        sysPower.setCreateTime(Date.from(Instant.now()));
        UserUtil.getCurrentUser().ifPresent(userDetail -> sysPower.setCreateBy(userDetail.getUsername()));
        sysPower.setEnable("1");
        sysPower.setOpenType("_iframe");
        sysPowerMapper.insertSelective(sysPower);
    }

    /**
     * 对菜单权限进行排序，用于前端树形菜单进行展示
     * @param permList 未排序的数据来源
     * @param powerDTOS 接收有序的数据
     * @param pid 最外层的父id（默认是0）
     */
    private void sort(List<PowerDTO> permList, LinkedList<PowerDTO> powerDTOS, String pid) {
        List<PowerDTO> collect = permList.stream()
                .filter(perm -> perm.getParentId().equals(pid))
                .sorted(Comparator.comparing(PowerDTO::getSort)).collect(Collectors.toList());
        if (CollUtil.isEmpty(collect)) {
            return;
        }
        collect.forEach(powerDTO -> {
            powerDTOS.add(powerDTO);
            sort(permList,powerDTOS,powerDTO.getPowerId());
        });
    }


    /**
     * 创建指定角色权限
     * @param roleId
     * @param permIds
     */
    private void createRolePerm(String roleId, List<String> permIds) {
        permIds.forEach(permId->{
            SysRolePower sysRolePower = new SysRolePower();
            sysRolePower.setId(IdUtil.objectId());
            sysRolePower.setRoleId(roleId);
            sysRolePower.setPowerId(permId);
            sysRolePower.setCreateTime(Date.from(Instant.now()));
            UserUtil.getCurrentUser().ifPresent(userDetail -> sysRolePower.setCreateBy(userDetail.getUsername()));
            sysRolePowerMapper.insertSelective(sysRolePower);
        });
    }

    private void checkRoleCode(String roleCode) {
        SysRoleDTO sysRoleDTO = sysRoleMapper.selectByRoleCode(roleCode);
        if (Objects.nonNull(sysRoleDTO)) {
            throw new BadRequestException(ErrorCode.ROLE_REPEATED);
        }
    }
}
